/**********************************************************************
 Copyright (C) 2010 Teppo Eeva

 This file is part of Arithmetic Game.
 For more information, see <http://code.google.com/p/arithmetic-game/>

 Arithmetic Game is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Arithmetic Game is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Arithmetic Game.  If not, see <http://www.gnu.org/licenses/>.
 **********************************************************************/

#include "mainwindow.h"
#include "arithengine.h"
#ifndef QT_NO_SOUND
#include "audiomanager.h"
#endif

#include "highscoremanager.h"
#if defined Q_OS_SYMBIAN || defined Q_ARITHMETIC_GAME_ANDROID
#include "ui_mainwindow_mobile.h"
#else
#include "ui_mainwindow.h"
#endif

#include "aboutdialog.h"
#include "settingsdialog.h"
#include "highscoredialog.h"
#include "highscoreitem.h"
#include "arithgame.h"
#include <QDebug>
#include <QSettings>
#include <QLabel>
#include <QPixmap>
#include <QSizePolicy>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    retranslateUi();
#ifdef Q_OS_SYMBIAN
    ui->spacerWidget->setHidden( true );
#endif // Q_OS_SYMBIAN
    m_engine = new ArithEngine( this );
#ifndef QT_NO_SOUND
    m_audioManager = new AudioManager( this );
#endif //QT_NO_SOUND
    m_aboutDialog = new AboutDialog(this);
    m_settingsDialog = new SettingsDialog(this);

    m_highScoreManager = new HighScoreManager();
    m_highScoreManager->loadHighStores(settingsName);

    handleGeometry(); //restore UI settings
    setWindowTitle(tr("arithmetic game"));

    connect( ui->startButton, SIGNAL(clicked()), m_engine, SLOT(startGame()));
    // Update progress bar automatically when engine emits an event about elapsed time
    connect( m_engine, SIGNAL(elapsedTimeChanged(int)), ui->remainingTimeBar, SLOT(setValue(int)));
#ifndef QT_NO_SOUND
    // Play sound effects
    connect( m_engine, SIGNAL(correctAnswerSubmitted()), m_audioManager, SLOT(playCorrect()));
    connect( m_engine, SIGNAL(incorrectAnswerSubmitted(int)), m_audioManager, SLOT(playFault()));
    connect( m_engine, SIGNAL(levelCompleted(int)), m_audioManager, SLOT(playBonus()));
    connect( m_engine, SIGNAL(readyToStartNextLevel(int)), m_audioManager, SLOT(stopBonus()));
    connect( m_engine, SIGNAL(gameOver(int,int)), m_audioManager, SLOT(playGameOver()));
#endif //QT_NO_SOUND
    // Insert icons when answered
    connect( m_engine, SIGNAL(correctAnswerSubmitted()), this, SLOT(insertCorrectIcon()));

    // Update score automatically when score changes are emited by engine
    connect( m_engine, SIGNAL(scoreChanged(int)), ui->scoreDisplay, SLOT(display(int)));

    connect( m_engine, SIGNAL(gameOver(int,int)), this, SLOT(finalizeGame(int,int)));
    connect( m_engine, SIGNAL(levelCompleted(int)), this, SLOT(finalizeLevel(int)));
    connect( m_engine, SIGNAL(readyToStartNextLevel(int)), this, SLOT(prepareForNextLevel(int)));

    connect( ui->answerEdit, SIGNAL(returnPressed()), this, SLOT(handleAnswer()));
#ifdef Q_ARITHMETIC_GAME_ANDROID
    connect( ui->pushButton, SIGNAL(clicked()), this, SLOT(handleAnswer()));
#endif //Q_ARITHMETIC_GAME_ANDROID
    connect( m_engine, SIGNAL(newQuestionAvailable()), this, SLOT(updateQuestion())); 
#ifndef QT_NO_SOUND
    connect( m_settingsDialog, SIGNAL(audioEffectOptionUpdated(bool)), m_audioManager, SLOT(enableAudio(bool)) );
#endif //QT_NO_SOUND
    connect( m_settingsDialog, SIGNAL(difftLevelOptionUpdated(ArithDiffLevel)), m_engine, SLOT(setDiffLevel(ArithDiffLevel)));
    connect( m_settingsDialog, SIGNAL(languageOptionUpdated()), this, SLOT(retranslateUi()));
    m_engine->setDiffLevel( m_settingsDialog->difficultyLevel());
#ifndef QT_NO_SOUND
    m_audioManager->enableAudio( m_settingsDialog->isSoundsEnabled() );
#endif //QT_NO_SOUND
    updateMenu();
    } 

MainWindow::~MainWindow()
{
    handleGeometry(false); //store UI settings

    delete m_highScoreManager;
    delete ui;
}

void MainWindow::startGame()
{
    ui->answerEdit->setEnabled(true);
    ui->answerEdit->setFocus(Qt::OtherFocusReason);
    ui->startButton->setEnabled(false);
    ui->actionSettings->setDisabled(true);
    ui->scoreDisplay->display( m_engine->score() );
    ui->levelDisplay->display( m_engine->level());
    ui->remainingTimeBar->setMaximum( m_engine->maxTime());    
#ifdef Q_OS_SYMBIAN
    this->showFullScreen();
#endif
    removeCorrectIcons();
}

void MainWindow::handleAnswer()
{
    QString answer = ui->answerEdit->text();
    int answerInt = answer.toInt();
    m_engine->handleAnswer( answerInt );
    ui->answerEdit->clear();
    ui->scoreDisplay->display( m_engine->score());
    ui->remainingTimeBar->setMaximum( m_engine->maxTime());
}

void MainWindow::finalizeGame(int score, int level)
{
    ui->answerEdit->setEnabled(false);
    ui->startButton->setEnabled(true);
    ui->actionSettings->setEnabled(true);

    HighScoreItem newItem;
    newItem.m_score = score;
    newItem.m_level = level;
    m_highScoreManager->suggestNewHighScore(newItem, m_settingsDialog->difficultyLevel());

    ui->startButton->setText(tr("Start game"));
    ui->startButton->setFocus(Qt::OtherFocusReason);
#ifdef Q_OS_SYMBIAN
    this->showMaximized();
#endif

}

void MainWindow::finalizeLevel(int level)
{
    Q_UNUSED(level);
    ui->answerEdit->setEnabled(false);
    ui->startButton->setEnabled(false);
}

void MainWindow::prepareForNextLevel(int level)
{
    Q_UNUSED(level);

    ui->startButton->setEnabled(false);
    ui->startButton->setEnabled(true);
    ui->startButton->setFocus(Qt::ActiveWindowFocusReason);
    ui->remainingTimeBar->setValue(0);
    ui->startButton->setText(QString(tr("Start level %1")).arg(level));
    ui->levelDisplay->display( m_engine->level());
}

void MainWindow::updateQuestion()
{
    ui->value1Text->setText( QString( "%1").arg(m_engine->question().value1()));
    ui->value2Text->setText( QString( "%1").arg(m_engine->question().value2()));
    ui->opText->setText( m_engine->question().opText());
    ui->answerEdit->clear();
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        retranslateUi();
        break;
    default:
        break;
    }
}

void MainWindow::handleGeometry(bool restore)
{
    QSettings settings(settingsName);

    if(restore)
    {
        qDebug() << "restore window settings";
#ifdef Q_OS_SYMBIAN
    {
        //full screen in symbian
        return;
    }
#endif //Q_OS_SYMBIAN
        QPoint pos = settings.value("pos").toPoint();
        QSize size = settings.value("size").toSize();
        QByteArray state = settings.value("state", QByteArray()).toByteArray();


        restoreState(state);

        qDebug() << "restore size" << size.width() << "," << size.height();

        if( size != QSize(600,400) ) //poor logic here.
        {
            qDebug() << "using default size";
            size = QSize(600,400);
        }

        resize(size);

        move(pos);
    }
    else
    {
        qDebug() << "store settings";
        settings.setValue("pos", pos());
        settings.setValue("size", size());
        settings.setValue("state", saveState());
    }
}

void MainWindow::showAbout()
{
    qDebug() << "Show About dialog";
#ifdef Q_OS_SYMBIAN
    {
    //full screen in symbian
    m_aboutDialog->showMaximized();
    }
#else //Q_OS_SYMBIAN
    {
    m_aboutDialog->show();
    }
#endif //Q_OS_SYMBIAN
}

void MainWindow::showSettings()
{
    qDebug() << "Show Settings dialog";
    m_settingsDialog->show();
}

void MainWindow::showHighScores()
{
    qDebug() << "Show High scores dialog";
    HighScoreDialog dialog;
    connect( &dialog, SIGNAL(resetHighScores()), m_highScoreManager, SLOT(resetHighScores()) );
    dialog.exec(*m_highScoreManager, m_settingsDialog->difficultyLevel());
}

void MainWindow::retranslateUi()
{
    qDebug() << "retranslateUi";
}

void MainWindow::insertCorrectIcon()
{
#ifndef Q_OS_SYMBIAN
        QLabel* label = new QLabel(this->centralWidget());
    label->setAlignment(Qt::AlignCenter);
    label->setPixmap(QPixmap(":/icons/bin/correct.svg"));

    QSizePolicy labelSizePolicy = label->sizePolicy();
    labelSizePolicy.setHorizontalStretch(1);
    label->setSizePolicy(labelSizePolicy);

    ui->horizontalLayoutIcons->insertWidget(0, label);

    QSizePolicy spacerSizePolicy = ui->spacerWidget->sizePolicy();
    spacerSizePolicy.setHorizontalStretch(10 - (ui->horizontalLayoutIcons->count() - 1));
    ui->spacerWidget->setSizePolicy(spacerSizePolicy);
#endif // Q_OS_SYMBIAN
}

void MainWindow::removeCorrectIcons()
{
#ifndef Q_OS_SYMBIAN
    for (int i = ui->horizontalLayoutIcons->count() - 1; i >= 0; --i)
    {
        QLayoutItem* item = ui->horizontalLayoutIcons->itemAt(i);
        if (item->widget() != ui->spacerWidget)
        {
            item->widget()->hide();
            ui->horizontalLayoutIcons->removeItem(item);
            delete item;
        }
    }
#endif // Q_OS_SYMBIAN
}

void MainWindow::updateMenu()
{
#ifdef Q_OS_SYMBIAN
    ui->menubar->clear();
    QAction* startAct = new QAction(tr("Start game"), this );
    connect( startAct, SIGNAL(triggered()), m_engine, SLOT(startGame()) );
    connect( startAct, SIGNAL(triggered()), this, SLOT(startGame()) );
    ui->menubar->addAction( startAct );
    ui->menubar->addAction( ui->actionHighScore );
    ui->menubar->addAction( ui->actionSettings );
    ui->menubar->addAction( ui->actionAbout );
    ui->menubar->addSeparator();
    ui->menubar->addAction( ui->actionClose );
#endif // Q_OS_SYMBIAN 
    connect( ui->startButton, SIGNAL(clicked()), this, SLOT(startGame()));
    connect( ui->actionHighScore, SIGNAL(triggered()), this, SLOT(showHighScores()));
    connect( ui->actionSettings, SIGNAL(triggered()), this, SLOT(showSettings())); 
    connect( ui->actionAbout, SIGNAL(triggered()), this, SLOT(showAbout()) ); 
    // Close applicaton when Close menu item is selected
    connect( ui->actionClose, SIGNAL(triggered()), qApp, SLOT(quit()));
}
